package bb.lanxing.activity.sport;

import static bb.lanxing.model.database.RouteBook.TYPE_SOURCE_WORKOUT;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.litepal.LitePal;

import com.alibaba.fastjson.JSON;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.TextureMapView;
import com.baidu.mapapi.model.LatLng;

import android.content.ContentValues;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import bb.lanxing.App;
import bb.lanxing.R;
import bb.lanxing.activity.base.BaseActivity;
import bb.lanxing.activity.deeplink.DeepLinkPathConstants;
import bb.lanxing.adapter.sport.SportFinishFeelingAdapter;
import bb.lanxing.fragment.sport.SportRecordChartFragment;
import bb.lanxing.fragment.sport.SportRecordDataFragment;
import bb.lanxing.manager.LevelPermissionMgr;
import bb.lanxing.manager.RemoteServiceManager;
import bb.lanxing.manager.SharedManager;
import bb.lanxing.model.WorkoutDatabaseHelper;
import bb.lanxing.model.database.ITrackPoint;
import bb.lanxing.model.database.IWorkout;
import bb.lanxing.model.database.LevelHP;
import bb.lanxing.model.database.RouteBook;
import bb.lanxing.model.database.Segment;
import bb.lanxing.model.database.Trackpoint;
import bb.lanxing.model.database.User;
import bb.lanxing.model.database.Workout;
import bb.lanxing.model.database.WorkoutOther;
import bb.lanxing.model.json.ServerUser;
import bb.lanxing.model.json.level.RuleConsume;
import bb.lanxing.network.BiCiCallback;
import bb.lanxing.network.MyHttpClient;
import bb.lanxing.network.NetSubscribe;
import bb.lanxing.util.BiCiCoorConverter;
import bb.lanxing.util.Log;
import bb.lanxing.util.RouteBookUtil;
import bb.lanxing.util.SportTypeResUtil;
import bb.lanxing.utils.MapUtil;
import bb.lanxing.view.BiciAlertDialogBuilder;
import okhttp3.Call;
import okhttp3.Request;
import okhttp3.Response;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

public class SportRecordDetailActivity extends BaseActivity {
    private final int[] feelingIconList = {R.drawable.ic_sport_experience_relaxed, R.drawable.ic_sport_experience_easy,
            R.drawable.ic_sport_experience_suitable, R.drawable.ic_sport_experience_tired,
            R.drawable.ic_sport_experience_very_tired};

    private final List<LatLng> points = new ArrayList<>();
    private TextureMapView textureMapView;
    private BaiduMap mBaiduMap;
    private LinearLayout afterSelected;
    private TextView feeling;
    private ImageView feelingIcon;
    private int listPosition;
    private Workout workout;

    private MapUtil mapUtil = MapUtil.getInstance();
    private FragmentManager mFragmentManager = getSupportFragmentManager();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sport_record_detail);

        ImageView back = findViewById(R.id.back);
        back.setOnClickListener(v -> onBackPressed());

        TextView title = findViewById(R.id.title);

        ImageView menu = findViewById(R.id.menu);
        menu.setOnClickListener(this::showPopupMenu);
        final String[] feelingNameList = {
                getString(R.string.sport_training_perception_very_relaxed),
                getString(R.string.sport_training_perception_relaxed),
                getString(R.string.sport_training_perception_moderation),
                getString(R.string.sport_training_perception_little_tired),
                getString(R.string.sport_training_perception_very_tired)
        };
        textureMapView = findViewById(R.id.textureMapView);
        mBaiduMap = textureMapView.getMap();
        mBaiduMap.setOnMapLoadedCallback(() -> setMapCenterAndRange(points));

        LinearLayout beforeSelected = findViewById(R.id.beforeSelected);
        RecyclerView feelingList = findViewById(R.id.feelingList);
        feelingList.setLayoutManager(new GridLayoutManager(this, 5));
        SportFinishFeelingAdapter feelingAdapter = new SportFinishFeelingAdapter(feelingNameList);
        feelingAdapter.setOnItemClickListener(position -> {
            beforeSelected.setVisibility(View.GONE);
            afterSelected.setVisibility(View.VISIBLE);
            feeling.setText(feelingNameList[position]);
            feelingIcon.setImageResource(feelingIconList[position]);
            if (workout != null) {
                workout.feeling = position + 1;
                ContentValues contentValues = new ContentValues();
                contentValues.put("feeling", workout.feeling);
                workout.update(contentValues);
            }
        });
        feelingList.setAdapter(feelingAdapter);
        afterSelected = findViewById(R.id.afterSelected);
        feeling = findViewById(R.id.feeling);
        feelingIcon = findViewById(R.id.feelingIcon);

        listPosition = getIntent().getIntExtra("position", -1);
        workout = Workout.getByServerId(getIntent().getLongExtra("workoutServerId", 0));
        if (workout == null) {
            return;
        }
        Log.i("SportRecordDetailActivity workout id = " + workout.id);
        title.setText(SportTypeResUtil.getTypeTextRes(workout.getSport()));

        if (mFragmentManager != null && !mFragmentManager.isDestroyed() && !mFragmentManager.isStateSaved()) {
            mFragmentManager.beginTransaction().add(R.id.dataContainer, new SportRecordDataFragment(workout))
                    .commit();
        }

        mapUtil.init(textureMapView);

        if (workout.feeling > 0) {
            beforeSelected.setVisibility(View.GONE);
            afterSelected.setVisibility(View.VISIBLE);
            feeling.setText(feelingNameList[workout.feeling - 1]);
            feelingIcon.setImageResource(feelingIconList[workout.feeling - 1]);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        // 在重新启用Activity时，重新绘制地图
        mapUtil.onResume();

        List<ITrackPoint> trackpointList = workout.getByWorkoutForMap();
        if (trackpointList == null || trackpointList.isEmpty()) {
            loadData(workout.getServerId());
        } else {
            showData();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        // 在Activity暂停或不可见时，暂停地图的渲染
        mapUtil.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 移除所有的监听器
        // ...
        Log.e("bb.lanxing onDestory", "before mBaiduMap");
        // 清理地图资源
        mapUtil.clear();
        // 释放地图资源
        Log.e("bb.lanxing onDestory", "after mBaiduMap");
    }

    private void loadData(long workoutId) {
        showLoadingDialog("加载中...", true);
        BiCiCallback biCiCallback = new BiCiCallback() {
            @Override
            public void onFailure(Request request, IOException e) {
                super.onFailure(request, e);
            }

            @Override
            public void onResponseString(@NonNull String string) {
                dismissLoadingDialog();
                if (!TextUtils.isEmpty(string)) {
                    try {
                        JSONObject jsonObject = new JSONObject(string);
                        int code = jsonObject.optInt("code");
                        if (200 == code) {
                            try {
                                JSONArray jSONArray = jsonObject.getJSONArray("rows");
                                List<Trackpoint> trackpointList = new ArrayList<>();
                                for (int i = 0; i < jSONArray.length(); i++) {
                                    Trackpoint trackpoint = new Trackpoint(jSONArray.getJSONObject(i));
                                    trackpoint.setWorkoutId(workout.getId());
                                    trackpointList.add(trackpoint);
                                }
                                String localWorkoutId = String.valueOf(workout.getId());
                                LitePal.deleteAll(Trackpoint.class, "workoutId=?", localWorkoutId);
                                WorkoutDatabaseHelper.saveTrackPoints(trackpointList);
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            showData();
                        }
                    } catch (JSONException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        MyHttpClient.downloadAllPoints(biCiCallback, workoutId);
    }

    private void showData() {
        new Thread(() -> mTrackPointHandler.sendMessage(Message.obtain())).start();
    }

    private final TrackPointHandler mTrackPointHandler = new TrackPointHandler();

    private class TrackPointHandler extends Handler {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (mFragmentManager != null && !mFragmentManager.isDestroyed() && !mFragmentManager.isStateSaved()) {
                mFragmentManager.beginTransaction().add(R.id.chartContainer, new SportRecordChartFragment(workout))
                        .commit();
            }
            //执行的UI操作
            List<ITrackPoint> trackPointList = workout.getByWorkoutForMap();
            Log.i("SportRecordDetailActivity handleMessage workout id = " + workout.id);
            List<Double> speeds = new ArrayList<>();
            for (ITrackPoint trackPoint : trackPointList) {
                if (trackPoint != null) {
                    points.add(BiCiCoorConverter.earth2Baidu(trackPoint.getLatLng()));
                    speeds.add(trackPoint.getSpeed());
                }
            }
            if (points.size() > 2 && mapUtil != null) {
                mapUtil.drawPolylineDynamic(points, speeds);
                mapUtil.drawStartAndEnd(points.get(0), points.get(points.size() - 1));
                setMapCenterAndRange(points);
            }
        }
    }

    private void setMapCenterAndRange(List<LatLng> points) {
        double[] gps = MapUtil.getFourCornerGps(points);
        LatLng center = MapUtil.getMapCenter(gps);
        float zoomLevel = MapUtil.getMapZoom(gps);
        mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLngZoom(center, zoomLevel));
    }

    private void showPopupMenu(View anchorView) {
        PopupMenu popupMenu = new PopupMenu(this, anchorView);
        popupMenu.inflate(R.menu.menu_sport_record_detail);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            popupMenu.setForceShowIcon(true);
        }
        popupMenu.setOnMenuItemClickListener(item -> {
            int itemId = item.getItemId();
            if (itemId == R.id.workout_merge) {
                if (App.getContext().isUserSignin()) {
                    new BiciAlertDialogBuilder(SportRecordDetailActivity.this)
                            .setTitle(R.string.workout_merge_tips_title).setMessage(R.string.workout_merge_tips_msg)
                            .setPositiveButton(R.string.confirm,
                                    (dialog, which) -> startActivity(
                                            new Intent(getApplicationContext(), HistoryListActivity.class)
                                                    .putExtra(HistoryListActivity.EXTRA_SHOW_MODE, 2)))
                            .show();
                } else {
                    App.getContext().userSignin();
                }
            } else if (itemId == R.id.workout_export) {
                exportLuShu(workout);
            } else if (itemId == R.id.delete) {
                onDeleteClick();
            }
            return true;
        });
        popupMenu.show();
    }

    private void exportLuShu(final IWorkout workout) {
        if (workout == null) {
            return;
        }
        showLoadingDialog(R.string.dialog_exporting, true);
        if (workout.getUserId() == App.getContext().getUserId()) {
            createRouteBook(workout.getServerId(), new Subscriber<>() {
                @Override
                public void onCompleted() {
                }

                @Override
                public void onError(Throwable e) {
                    dismissLoadingDialog();
                    App.getContext().showMessage(e.getMessage());
                }

                @Override
                public void onNext(Long aLong) {
                    dismissLoadingDialog();
                    App.getContext().showMessage(R.string.mine_level_toast_export_to_lushu_successful);
                }
            });
        } else if (workout instanceof Workout) {
            exportFromLocalWorkout(workout, false);
        } else {
            downloadFromServerWorkoutWithCheck(workout);
        }
    }

    private void downloadFromServerWorkoutWithCheck(final IWorkout workout) {
        if (workout.isExport() || LevelPermissionMgr.getInstance().checkPermission(1)) {
            downloadFromServerWorkout(workout, false);
            return;
        }
        dismissLoadingDialog();
        showCreditsDialog(workout);
    }

    private void showCreditsDialog(final IWorkout workout) {
        new BiciAlertDialogBuilder(this).setMessage("当日免费转路书已超过次数限制，是否花费10积分下载？")
                .setPositiveButton(R.string.dialog_btn_ok, (dialog, which) -> downloadFromServerWorkout(workout, true))
                .setNegativeButton(R.string.dialog_btn_cancel, null).show();
    }

    private void downloadFromServerWorkout(final IWorkout workout, final boolean needCredits) {
        ServerUser user;
        showLoadingDialog(R.string.dialog_exporting, true);
        final RouteBook routeBook = new RouteBook();
        routeBook.setUuid(workout.getUuid());
        routeBook.setServerId(workout.getServerId());
        routeBook.setServerType(TYPE_SOURCE_WORKOUT);
        routeBook.setSport(workout.getSport());
        routeBook.setCreateTime(System.currentTimeMillis());
        routeBook.setSourceType(RouteBook.TYPE_IMPORT);
        routeBook.setTitle(workout.getTitle());
        routeBook.setUserId(workout.getUserId());
        if ((workout instanceof WorkoutOther) && (user = ((WorkoutOther) workout).getUser()) != null) {
            routeBook.setUsername(user.getName());
            routeBook.setUserAvatar(user.getPhotoUrl());
        }
        MyHttpClient.downloadRouteBook(new BiCiCallback() {
            String requestUrl = null;

            @Override
            public void onResponse(Response response) throws IOException {
                this.requestUrl = response.request().url().toString();
                super.onResponse(response);
            }

            @Override
            public void onResponseFail(String errMsg) {
                super.onResponseFail(errMsg);
                dismissLoadingDialog();
            }

            @Override
            public void onResponseString(@NonNull String string) throws JSONException {
                Log.v(TAG, "downloadLushu, requestUrl = " + this.requestUrl);
                if (this.requestUrl.toLowerCase().endsWith(
                        App.getContext().getHttpDomain() == 1 ? DeepLinkPathConstants.FILE_SUFFIX_GPX : ".gpxtest")) {
                    RouteBookUtil.parseGpxFile(string, routeBook);
                } else {
                    if (this.requestUrl.toLowerCase()
                            .endsWith(App.getContext().getHttpDomain() == 1 ? ".json" : ".jsontest")) {
                        RouteBook routeBook2 = routeBook;
                        RouteBookUtil.parseDirection(string, null, routeBook2, routeBook2.getSourceType());
                    } else {
                        RouteBookUtil.parseGpxFile(string, routeBook);
                    }
                }
                dismissLoadingDialog();
                processPermissionResponse(routeBook, needCredits);
                SharedManager.getInstance().setCreateRouteBookDownloadIsNeedRefresh(1);
                App.getContext().sendBroadcast(new Intent(RouteBook.ACTION_WORKOUT_CREATE_LUSHU));
            }
        }, routeBook.getServerType(), routeBook.getServerId());
    }

    private void processPermissionResponse(RouteBook routeBook, boolean needCredits) {
        LevelHP levelHP = LevelPermissionMgr.getInstance().getLevelHP();
        RuleConsume ruleConsume = LevelPermissionMgr.getInstance().getRule().getRuleConsume();

        if (routeBook != null && routeBook.getId() != null) {
            String str = "可以在【路书】-【我的】-【已下载】中找到。";
            if (needCredits) {
                if ((ruleConsume) != null) {
                    str = "可以在【路书】-【我的】-【已下载】中找到。" + App.getContext()
                            .getString(R.string.mine_level_toast_consume_credits, ruleConsume.getWorkoutExport());
                }
            } else {
                if (!routeBook.isExport()) {
                    LevelPermissionMgr.getInstance().updatePermisstion(1);
                }
                if (levelHP != null) {
                    str = "可以在【路书】-【我的】-【已下载】中找到。" + App.getContext().getString(R.string.mine_level_toast_consume_count,
                            levelHP.getWorkoutExport());
                }
            }
            App.getContext().showMessage(str);
            return;
        }

        App.getContext().showMessage(R.string.mine_level_toast_export_to_lushu_failed);
    }

    private void createRouteBook(long workoutId, Subscriber<Long> subscriber) {
        Observable.create(new NetSubscribe(MyHttpClient.createRouteBookByWorkoutId(workoutId)))
                .subscribeOn(Schedulers.io())
                .map(str -> JSON.parseObject(str).getJSONObject("data").getLong("serverId"))
                .observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);
    }

    private void exportFromLocalWorkout(IWorkout workout, final boolean isMyWorkout) {
        showLoadingDialog(R.string.dialog_exporting, true);
        Observable.just(workout).subscribeOn(Schedulers.io()).flatMap(workout2 -> {
            RouteBook byId;
            long exportWorkoutToLushu = RouteBookUtil.exportWorkoutToRouteBook(SportRecordDetailActivity.this,
                    workout2.getId(), isMyWorkout);
            if (exportWorkoutToLushu > 0 && (byId = RouteBook.getById(exportWorkoutToLushu)) != null) {
                byId.setServerId(workout2.getServerId());
                byId.setServerType(TYPE_SOURCE_WORKOUT);
                byId.setTitle(workout2.getTitle());
                byId.setUserId(workout2.getUserId());
                User signinUser = App.getContext().getSigninUser();
                if (signinUser != null) {
                    byId.setUsername(signinUser.getName());
                }
                byId.setDistance(workout2.getDistance());
                if (!TextUtils.isEmpty(workout2.getUuid())) {
                    byId.setUuid(workout2.getUuid());
                }
                byId.save();
            }
            return Observable.just(exportWorkoutToLushu);
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(aLong -> {
            dismissLoadingDialog();
        });
    }

    private void onDeleteClick() {
        if (RemoteServiceManager.getInstance().isSporting()) {
            Workout byServerId = Workout.getByServerId(SharedManager.getInstance().getUserId());
            if (byServerId != null && byServerId.getWorkStatus() != Workout.STATUS_STOPED
                    && this.workout.getUuid().equals(byServerId.getUuid())) {
                toast(R.string.workout_toast_sporting_cannot_delete);
                return;
            } else {
                showDeleteDialog();
                return;
            }
        }
        showDeleteDialog();
    }

    private void showDeleteDialog() {
        new BiciAlertDialogBuilder(this).setTitle(R.string.workout_dialog_delete_title)
                .setMessage(R.string.workout_dialog_delete_content)
                .setPositiveButton(R.string.delete, (dialog, which) -> deleteWorkout())
                .setNegativeButton(R.string.not_delete, null).show().setCanceledOnTouchOutside(true);
    }

    public void deleteWorkout() {
        if (workout.getServerId() > 0) {
            MyHttpClient.deleteWorkout(new BiCiCallback() {
                @Override
                public void onResponseFail(String errMsg) {
                    super.onResponseFail(errMsg);
                }

                @Override
                public void onResponse(@NonNull Call call, @NonNull Response response) {
                    Log.d(TAG, "onResponse...response=" + response);
                }

                @Override
                public void onResponseString(@NonNull String string) throws JSONException {
                    toast(R.string.workout_delete_done);
                }
            }, workout.getServerId(), 0);
        }
        workout.delete();
        Trackpoint.deleteByWorkout(workout.getId());
        Segment.deleteByWorkout(workout.getId());
        Intent intent = new Intent();
        intent.putExtra("position", listPosition);
        setResult(RESULT_OK, intent);
        finish();
    }
}